package cn.clj;

import java.math.BigInteger;

public class CljUtil {
    public static String toStr(String xs)
    {
        StringBuilder sb = new StringBuilder ();
        sb.append('"');
        for (int i = 0, n = xs.length(); i < n; i++) {
            char c = xs.charAt(i);
            if (c == '"')
                sb.append("\\\"");
            else if (c == '\\')
                sb.append("\\\\");
            else if (c == '\n')
                sb.append("\\n");
            else if (c == '\r')
                sb.append("\\r");
            else if (c == '\t')
                sb.append("\\t");
            else if (Character.isISOControl(c))
                sb.append(String.format("\\x%02x", (int) c));
            else
                sb.append(c);
        }
        sb.append('"');
        return sb.toString();
    }

    /**
     * 读取字符串中  后面的八进制数字表示的字符。
     */
    public static char getOctChar(CljCharIterator ci)
            throws Exception
    {
        int result = ci.current() - '0';
        for (int i = 0; ci.next() && i < 2; i++) {
            char ch = ci.current();
            if ('0' <= ch && ch <= '9')
                result = (result << 3) + ch - '0';
            else
                break;
        }
        return (char) result;
    }

    /**
     * 读取字符串中 x 后面的十六进制字符
     */
    public static char getHexChar(CljCharIterator ci)
            throws Exception
    {
        int result = 0;
        for (int i = 0; ci.next() && i < 2; i++) {
            char ch = ci.current();
            if ('0' <= ch && ch <= '9')
                result = (result << 4) + ch - '0';
            else if ('A' <= ch && ch <= 'F')
                result = (result << 4) + ch - 'A' + 10;
            else if ('a' <= ch && ch <= 'f')
                result = (result << 4) + ch - 'a' + 10;
            else
                break;
        }
        return (char) result;
    }

    public static String getString(final CljCharIterator myCharIterator) throws Exception {
        StringBuilder sb = new StringBuilder();
        // 移动到 " 的后一个字符
        myCharIterator.next();

        for (;;)
        {
            char c = myCharIterator.current();
            if (c == '"')
            {
                return sb.toString();
            }
            else if (c == '\n')
            {
                throw new Exception("string not terminated: " + toStr(sb.toString()));
            }
            else if (c == '\\')
            {
                myCharIterator.next();
                char t = myCharIterator.current();
                switch (t)
                {
                    case '0': case '1': case '2': case '3':
                    case '4': case '5': case '6': case '7':
                    sb.append(getOctChar(myCharIterator));
                    // 在八进制下预先读取了
                    continue;
                    case 'x':
                        sb.append(getHexChar(myCharIterator));
                        // 在十六进制下预先读取
                        continue;
                    case '\"':
                        c = '\"';
                        break;
                    case '\\':
                        c = '\\';
                        break;
                    case 'a':
                        c = '\007';
                        break;
                    case 'b':
                        c = '\b';
                        break;
                    case 'f':
                        c = '\f';
                        break;
                    case 'n':
                        c = '\n';
                        break;
                    case 'r':
                        c = '\r';
                        break;
                    case 't':
                        c = '\t';
                        break;
                    case 'v':
                        c = '\013';
                        break;
                    default:
                        throw new Exception("错误解析：" + myCharIterator.current());
                }
            }

            sb.append(c);
            myCharIterator.next();
        }
    }

    /**
     * 尝试将字符串解释为数字
     *  失败时返回 null
     */
    public static Number tryToParseAsNumber(String s) {
        boolean isNegative = false;
        if (s.startsWith("-")) {
            isNegative = true;
            s = s.substring(1);
        }
        int radix = 10;
        if (s.startsWith("#") && s.length() >= 3) {
            switch (s.charAt(1)) {
                case 'b': case 'B':
                    radix = 2; break;
                case 'o': case 'O':
                    radix = 8; break;
                case 'x': case 'X':
                    radix = 16; break;
                default:
                    return null;
            }
            s = s.substring(2);
        }
        if (isNegative)
            s = "-" + s;
        try {
            return Integer.valueOf(s, radix);
        } catch (NumberFormatException ex) {}
        try {
            return new BigInteger(s, radix);
        } catch (NumberFormatException ex) {}
        if (radix == 10) {
            try {
                return Double.valueOf(s);
            } catch (NumberFormatException ex) {}
        }
        return null;
    }

    /**
     * 确定参数是否适合作为符号
     */
    public static boolean checkSymbol(String s) {
        for (int i = 0, n = s.length(); i < n; i++) {
            char c = s.charAt(i);
            if (! (('a' <= c && c <= 'z') ||
                    ('A' <= c && c <= 'Z') ||
                    ('0' <= c && c <= '9') ||
                    c == '_' || c == '&' || c == '$' ||
                    c == '*' || c == '/' || c == '%' ||
                    c == '+' || c == '-' || c == '<' ||
                    c == '>' || c == '=' || c == '!' ||
                    c == '?'))
                return false;
        }
        return true;
    }

}
